package com.bocloud.cmp.service.resource;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.bocloud.cmp.dao.BeanDetailDao;
import com.bocloud.cmp.dao.StorageDeviceDao;
import com.bocloud.cmp.entity.resource.StorageDevice;
import com.bocloud.cmp.enums.VMStatus;
import com.bocloud.cmp.interfaces.resource.StorageDeviceService;
import com.bocloud.cmp.model.StorageDeviceBean;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.ssh.SSH;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.coordinator.harmony.HarmonyLock;
import com.bocloud.coordinator.harmony.LockFactory;
import com.google.common.collect.Maps;

@Service("storageDeviceService")
public class StorageDeviceServiceImpl implements StorageDeviceService {

	private static Logger logger = LoggerFactory.getLogger(StorageDeviceServiceImpl.class);
	@Autowired
	private StorageDeviceDao storageDeviceDao;
	@Autowired
	private BeanDetailDao beanDetailDao;
	@Autowired
	private LockFactory lockFactory;

	@Override
	public BsmResult create(StorageDevice device, Long userId) {
		try {
			device.setCreaterId(userId);
			device.setMenderId(userId);
			device.setStatus(VMStatus.STOPPED.name());
			storageDeviceDao.save(device);
		} catch (Exception e) {
			logger.error("Create device fail:", e);
			return new BsmResult(false, "添加失败", "", "");
		}
		return new BsmResult(true, device, "添加成功");
	}

	@Override
	public BsmResult modify(StorageDeviceBean bean, Long userId) {
		String path = StorageDevice.class.getSimpleName() + "_" + bean.getId();
		HarmonyLock lock = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时", "", "");
			}

			StorageDevice device = this.storageDeviceDao.query(bean.getId());
			if (null == device) {
				logger.warn("StorageDevice does not exist!");
				return new BsmResult(false, "数据不存在", "", "");
			}
			BeanUtils.copyProperties(bean, device);
			device.setMenderId(userId);
			this.storageDeviceDao.update(device);
			return new BsmResult(true, "修改成功");
		} catch (Exception e) {
			logger.error("Modify device fail:", e);
			return new BsmResult(false, "修改失败", null, null);
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

	@Override
	public BsmResult remove(Long id, Long userId) {
		String path = StorageDevice.class.getSimpleName() + "_" + id;
		HarmonyLock lock = null;
		boolean result = false;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时");
			}
			StorageDevice object = this.storageDeviceDao.query(id);
			if (null == object) {
				logger.warn("StorageDevice does not exist!");
				return new BsmResult(false, "数据不存在", "", "");
			}
			result = this.storageDeviceDao.remove(id, userId);
			return result ? new BsmResult(true, "删除成功") : new BsmResult(true, "已被删除");
		} catch (Exception e) {
			logger.error("Remove device fail:", e);
			return new BsmResult(false, "删除失败", null, null);
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

	@Override
	public BsmResult detail(Long id) {
		StorageDevice device = null;
		try {
			device = this.beanDetailDao.getStorageDeviceBean(id);
			if (null == device) {
				logger.warn("StorageDevice does not exist!");
				return new BsmResult(false, device, "数据不存在");
			}
		} catch (Exception e) {
			logger.error("Query device fail:", e);
			return new BsmResult(false, "查询失败", null, null);
		}
		return new BsmResult(true, device, "查询成功");
	}

	@Override
	public BsmResult list(int page, int rows, List<Param> params, Map<String, String> sorter, Boolean simple) {
		List<StorageDevice> list = null;
		List<SimpleBean> beans = null;
		int total = 0;
		GridBean gridBean = null;
		try {
			if (null == params) {
				params = new ArrayList<Param>();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			total = this.storageDeviceDao.count(params);
			if (simple) {
				beans = this.storageDeviceDao.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				list = this.storageDeviceDao.list(page, rows, params, sorter);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BsmResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query device list fail:", e);
			return new BsmResult(false, "查询失败", null, null);
		}
	}

	@Override
	public BsmResult start(Long id) {
		String path = StorageDevice.class.getSimpleName() + "_" + id;
		HarmonyLock lock = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时", "", "");
			}
			StorageDevice device = storageDeviceDao.query(id);
			String starCommand = device.getStartCommand();
			if (null == starCommand) {
				return new BsmResult(false, "请添加启动脚本!");
			}
			Integer port = null;
			if (!StringUtils.isEmpty(device.getServicePort())) {
				port = Integer.valueOf(device.getServicePort());
			}
			SSH ssh = null;
			if (null == port) {
				ssh = new SSH(device.getManageIp(), device.getUsername(), device.getPassword());
			} else {
				ssh = new SSH(device.getManageIp(), device.getUsername(), device.getPassword(), port);
			}
			if (!ssh.connect()) {
				logger.error("ssh connect failure!");
				return new BsmResult(false, "启动失败!");
			}
			String result = ssh.executeWithResult(starCommand);
			if (null == result) {
				return new BsmResult(false, "启动失败!");
			}
			device.setStatus(VMStatus.RUNNING.name());
			storageDeviceDao.update(device);
			return new BsmResult(true, "启动成功!");
		} catch (Exception e) {
			logger.error("start storageDevice failure:", e);
			return new BsmResult(false, "启动失败!");
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

	@Override
	public BsmResult stop(Long id) {
		String path = StorageDevice.class.getSimpleName() + "_" + id;
		HarmonyLock lock = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时", "", "");
			}
			StorageDevice device = storageDeviceDao.query(id);
			String stopCommand = device.getStopCommand();
			if (null == stopCommand) {
				return new BsmResult(false, "请添加停止脚本!");
			}
			Integer port = null;
			if (!StringUtils.isEmpty(device.getServicePort())) {
				port = Integer.valueOf(device.getServicePort());
			}
			SSH ssh = null;
			if (null == port) {
				ssh = new SSH(device.getManageIp(), device.getUsername(), device.getPassword());
			} else {
				ssh = new SSH(device.getManageIp(), device.getUsername(), device.getPassword(), port);
			}
			if (!ssh.connect()) {
				logger.error("ssh connect failure!");
				return new BsmResult(false, "停止失败!");
			}
			String result = ssh.executeWithResult(stopCommand);
			if (null == result) {
				return new BsmResult(false, "停止失败!");
			}
			device.setStatus(VMStatus.STOPPED.name());
			storageDeviceDao.update(device);
			return new BsmResult(true, "停止成功!");
		} catch (Exception e) {
			logger.error("stop storageDevice failure:", e);
			return new BsmResult(false, "停止失败!");
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

	@Override
	public BsmResult batchtStart(String params, Long userId) {
		try {
			String[] idArray = params.split(",");// 获取要启动的存储设备的id
			String storageDeviceName = "";// 启动失败的存储设备的名称
			if (null != idArray && idArray.length > 0) {
				for (String id : idArray) {
					// 启动存储设备
					BsmResult result = this.start(Long.parseLong(id));
					if (!result.isSuccess()) {
						// 查询启动失败的存储设备
						StorageDevice device = storageDeviceDao.query(Long.parseLong(id));
						storageDeviceName += device.getName();
					}
				}
			}
			// 返回启动失败的存储设备的名称
			if (null != storageDeviceName && storageDeviceName.length() > 0) {
				return new BsmResult(false, "存储设备" + storageDeviceName + "启动失败");
			}
		} catch (Exception e) {
			logger.error("device start fail:", e);
			return new BsmResult(false, "存储设备启动失败");
		}
		return new BsmResult(true, "存储设备启动成功");
	}

	@Override
	public BsmResult batchStop(String params, Long userId) {
		try {
			String[] idArray = params.split(",");// 获取要删除的所有设备的id
			String storageDeviceName = "";// 停止失败的存储设备的名称
			if (null != idArray && idArray.length > 0) {
				for (String id : idArray) {
					// 停止存储设备
					BsmResult result = this.stop(Long.parseLong(id));
					if (!result.isSuccess()) {
						// 获取停止失败的存储设备的名称
						StorageDevice device = storageDeviceDao.query(Long.parseLong(id));
						storageDeviceName += device.getName();
					}
				}
			}
			// 返回停止失败的存储设备
			if (null != storageDeviceName && storageDeviceName.length() > 0) {
				return new BsmResult(false, "存储设备" + storageDeviceName + "停止失败");
			}
		} catch (Exception e) {
			logger.error("存储设备停止失败", e);
			return new BsmResult(false, "存储设备停止失败");
		}
		return new BsmResult(true, "存储设备启动成功");
	}

	@Override
	public BsmResult batchRemove(String params, Long userId) {
		try {
			String[] idArray = params.split(",");// 获取要删除的所有设备的id
			String storageDeviceName = "";// 删除失败的存储设备的名称
			if (null != idArray && idArray.length > 0) {
				for (String id : idArray) {
					// 删除存储设备
					BsmResult result = this.remove(Long.parseLong(id), userId);
					if (!result.isSuccess()) {
						// 查询删除失败的存储设备的名称
						StorageDevice device = storageDeviceDao.query(Long.parseLong(id));
						storageDeviceName += device.getName();
					}
				}
			}
			// 返回删除失败的存储设备的名称
			if (null != storageDeviceName && storageDeviceName.length() > 0) {
				return new BsmResult(false, "存储设备" + storageDeviceName + "删除失败");
			}
		} catch (Exception e) {
			logger.error("存储设备删除失败", e);
			return new BsmResult(false, "存储设备删除失败");
		}
		return new BsmResult(true, "存储设备删除成功");
	}

}
